Generally, an interpreted computer programming language is a language that avoids the need for explicit program compilation. Conventional (compiled) programming languages are “compiled” into a set of machine-specific instructions before being saved as an executable file. The saved executable file is often referred to as a “binary” file. For interpreted languages, by contrast, the code is saved in the same format in which it was programmed by the developer. While compiled programs generally run faster than interpreted programs because they do not need to be reduced to machine instructions at runtime, an interpreted language permits functionality not generally available within compiled code. For example, interpreted programs can modify themselves by adding or changing functions at runtime, and testing programs written using an interpreted language may not require compilation prior to each test. Examples of interpreted programming languages include JavaScript, Perl, Python, and Ruby. Languages that are first compiled to bytecode (e.g., Java, C#, etc.) may not be considered as strictly interpreted languages because their source code is compiled into bytecode, which is then evaluated (interpreted) by a virtual machine (VM) or interpreter (e.g., Java VM, .NET Common Language Runtime (CLR)). The systems and methods described herein can be used, however, to extract information from such interpreted, bytecode runtimes, and an application program written in such a language can be analyzed using the extracted information.
However, there are risks in creating valuable application code using interpreted computer code. One risk, for example, is that the intellectual property associated with the code may be easily exploited or compromised if the code is distributed without ample protections. Furthermore, because the code can essentially “morph” during interpretation and create new classes and methods on the fly, debugging applications written using interpreted code can be difficult and can depend on the application's run-time environment and its interactions with other applications. Therefore, testing applications written primarily or exclusively using interpreted languages while maintaining the proprietary nature of the application code is challenging. Improved systems and methods are therefore needed to facilitate such testing.